home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
DTP
/
DTP_TEX
/
3238.ZIP
/
DVIEPS2.ZIP
/
DVIFONTS.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-11-01
|
85KB
|
2,398 lines
/*=======================================================================
* Program : dvifonts.c
* Purpose : font related code for eps device driver
* Date : Oct 1988
*========================================================================
* Compiler : Microsoft V5.1 C Compiler
* Linker : Microsoft V3.61 Linker
* Enviroment : MS-DOS 3.21
*========================================================================
* Edit History
*
* / / -gbm-
*
*======================================================================*/
#include "dvidefs.h"
#include "dvivars.h"
extern double mag_table[99];
/***********************************************************************
Compute the actual size factor given the integer approximation unmodsize
= (magnification factor)*1000. Values not found in the table are
rounded to the nearest table entry; this ensures that rounding errors,
or user magnification parameter input errors result in something
reasonable. mag_table[] has a wider range of magnifications available
than most sites will have, and can be used to find a nearest match font
when one is missing.
***********************************************************************/
double actfact(register unsigned long int unmodsize)
{
register int k;
register unsigned long int tab_entry;
for (k = 1; k < MAGTABSIZE; ++k)
{
tab_entry = MAGSIZE(mag_table[k]); /* round entry */
if (unmodsize < tab_entry) /* choose nearer of k-1,k entries */
{
if (unmodsize < MAGSIZE((mag_table[k-1] + mag_table[k])/2.0))
k--; /* choose smaller one */
break;
}
else if (unmodsize == tab_entry)
break;
}
mag_index = ((k < MAGTABSIZE) ? k : (MAGTABSIZE-1));/* set global index */
return((double)mag_table[mag_index]);
}
int chargf(c, outfcn) /* return 0 on success, and EOF on failure */
unsigned char c; /* current character value */
void (*outfcn)(); /* (possibly NULL) function to output current row */
{
unsigned int d; /* step in m index */
int do_output; /* FALSE if outfcn is NULL */
register unsigned int k; /* loop step */
register int m,n; /* column,row indices in image[n][m] */
long p; /* pointer into font file */
unsigned char paint_switch; /* alternates between BLACK and WHITE */
struct char_entry *tcharptr;/* temporary char_entry pointer */
register unsigned char the_byte; /* current command byte */
unsigned long int the_word; /* temporary result holder */
/* NB: We only test for equality with BLACK. WHITE is any non-zero
bit pattern, so we cannot test for equality with it */
#define BLACK ((unsigned char)0)
#define WHITE ((unsigned char)(!BLACK))
/*******************************************************************
This function is called to process a single character description in
the GF font file, and to set the character metrics hp, wp, xoffp,
and yoffp for it. The character description may start either at a
special (XXX) command, or at a beginning-of-character (BOC or BOC1)
command. It processes the character description up to, and
including, the end-of-character (EOC) command which terminates it.
The GF raster description is encoded in a complex form, but is
guaranteed to step across raster rows from left to right, and down
from the top row to bottom row, such that in references to
image[n][m], m never decreases in a row, and n never increases in a
character. This means that we only require enough memory space to
hold one row, provided that outfcn(c,yoff) is called each time a row
is completed. This is an important economization for
high-resolution output devices -- e.g. a 10pt character at 2400
dots/inch would require about 8Kb for the entire image, but fewer
than 25 bytes for a single row. A 72pt character (such as in the
aminch font) would need about 430Kb for the image, but only about
200 bytes for a row.
Access to bit m in the current row is controlled through the macros
SETBIT(m) and TESTBIT(m) so we need not be concerned about the
details of bit masking. Too bad C does not have a bit data type!
The row image is recorded in such a way that bits min_m .. max_m are
mapped onto bits 0 .. (max_m - min_m) in img_row[], so that
outfcn(c,yoff) should be relieved of any shifting operations.
outfcn(c,yoff) is NEVER called if either of hp or wp is <= 0, or if
if it is NULL.
*******************************************************************/
if ((c < FIRSTPXLCHAR) || (LASTPXLCHAR < c))
{
(void)warning(
"chargf(): Character value out of range for GF font file");
return(EOF);
}
tcharptr = &(fontptr->ch[c]);
p = (long)tcharptr->fontrp; /* font file raster pointer */
if (p < 0L)
{
(void)warning(
"chargf(): Requested character not found in GF font file");
return(EOF);
}
if (fseek(fontfp,p,0))
{
(void)warning(
"chargf(): fseek() failure for GF font file character raster");
return(EOF);
}
do_output = (int)(outfcn != (void(*)())NULL);
(void)skgfspec(); /* skip any GF special commands */
the_byte = (unsigned char)nosignex(fontfp,(unsigned char)1);
if ((the_byte != GFBOC) && (the_byte != GFBOC1))
{
(void)warning(
"chargf(): GF font file not positioned at BOC or BOC1 command");
return(EOF);
}
for (;;) /* loop with exit at EOC, or at BOC or BOC1 if no rasters */
{
switch (the_byte)
{
case GFPAINT0:
paint_switch = (unsigned char)(!paint_switch);
break;
case GFPAINT1:
d = (unsigned int)nosignex(fontfp,(unsigned char)1);
if (do_output && (paint_switch == BLACK))
{
for (k = 0; k < d; (++m, ++k))
SETBIT(m);
}
else
m += (int)d;
paint_switch = (unsigned char)(!paint_switch);
break;
case GFPAINT2:
d = (unsigned int)nosignex(fontfp,(unsigned char)2);
if (do_output && (paint_switch == BLACK))
{
for (k = 0; k < d; (++m, ++k))
SETBIT(m);
}
else
m += (int)d;
paint_switch = (unsigned char)(!paint_switch);
break;
case GFPAINT3: /* METAFONT never needs this */
d = (unsigned int)nosignex(fontfp,(unsigned char)3); /* NOTE: truncation */
if (do_output && (paint_switch == BLACK))
{
for (k = 0; k < d; (++m, ++k))
SETBIT(m);
}
else
m += (int)d;
paint_switch = (unsigned char)(!paint_switch);
break;
case GFBOC: /* beginning-of-character -- long form */
the_word = (unsigned long int)nosignex(fontfp,(unsigned char)4);
p = (long)signex(fontfp,(unsigned char)4);
if ((unsigned long int)c != the_word)
{
if (p < 0L)
{
(void)warning(
"chargf(): Requested character not found in back chain in GF font file");
return(EOF);
}
else
(void)fseek(fontfp,p,0); /* must follow back chain */
break;
}
else
{
min_m = (int)signex(fontfp,(unsigned char)4);
max_m = (int)signex(fontfp,(unsigned char)4);
min_n = (int)signex(fontfp,(unsigned char)4);
max_n = (int)signex(fontfp,(unsigned char)4);
}
if ((min_m < MIN_M) || (MAX_M < max_m) ||
(min_n < MIN_N) || (MAX_N < max_n))
{
(void)warning(
"chargf(): GF font file character box too large for me");
return(EOF);
}
m = min_m;
n = max_n;
paint_switch = WHITE;
img_words = (unsigned int)((max_m - min_m + 1 + 31) >> 5);
if (do_output)
(void)clrrow();
tcharptr->hp = (int)(max_n - min_n + 1);
tcharptr->wp = (int)(max_m - min_m + 1);
tcharptr->xoffp = -(int)(min_m);
tcharptr->yoffp = (int)(max_n);
if (!VISIBLE(tcharptr))
return(0); /* empty character raster -- nothing to output */
break;
case GFBOC1: /* beginning-of-character -- short form */
if (c != (unsigned char)nosignex(fontfp,(unsigned char)1))
{
(void)warning(
"chargf(): Requested character not found in GF font file");
return(EOF);
}
else
{
min_m = (int)nosignex(fontfp,(unsigned char)1);
max_m = (int)nosignex(fontfp,(unsigned char)1);
min_m = max_m - min_m;
min_n = (int)nosignex(fontfp,(unsigned char)1);
max_n = (int)nosignex(fontfp,(unsigned char)1);
min_n = max_n - min_n;
}
if ((min_m < MIN_M) || (MAX_M < max_m) ||
(min_n < MIN_N) || (MAX_N < max_n))
{
(void)warning(
"chargf(): GF font file character box too large for me");
return(EOF);
}
m = min_m;
n = max_n;
paint_switch = WHITE;
img_words = (unsigned int)((max_m - min_m + 1 + 31) >> 5);
if (do_output)
(void)clrrow();
tcharptr->hp = (int)(max_n - min_n + 1);
tcharptr->wp = (int)(max_m - min_m + 1);
tcharptr->xoffp = -(int)(min_m);
tcharptr->yoffp = (int)(max_n);
if (!VISIBLE(tcharptr))
return(0);/* empty character raster -- nothing to output */
break;
case GFEOC: /* end-of-character */
if (do_output)
{
(void)(*outfcn)(c,max_n-n); /* output current row */
(void)clrrow(); /* clear next one */
--n; /* advance to next row below */
for ( ; n >= min_n ; --n) /* output any remaining rows */
(void)(*outfcn)(c,max_n-n);
}
return(0); /* exit outer loop */
case GFSKIP0:
if (do_output)
{
(void)(*outfcn)(c,max_n-n); /* output current row */
(void)clrrow(); /* clear next one */
}
--n; /* advance to next row below */
m = min_m;
paint_switch = WHITE;
break;
case GFSKIP1:
if (do_output)
{
(void)(*outfcn)(c,max_n-n); /* output current row */
(void)clrrow(); /* clear next one */
}
--n; /* advance to next row below */
d = (unsigned int)nosignex(fontfp,(unsigned char)1);
if (do_output)
{
for (k = 0; k < d; (--n,++k)) /* output d white rows */
(void)(*outfcn)(c,max_n-n);
}
else
n -= (int)d;
m = min_m;
paint_switch = WHITE;
break;
case GFSKIP2:
if (do_output)
{
(void)(*outfcn)(c,max_n-n); /* output current row */
(void)clrrow(); /* clear next one */
}
--n; /* advance to next row below */
d = (unsigned int)nosignex(fontfp,(unsigned char)2);
if (do_output)
{
for (k = 0; k < d; (--n,++k)) /* output d white rows */
(void)(*outfcn)(c,max_n-n);
}
else
n -= (int)d;
m = min_m;
paint_switch = WHITE;
break;
case GFSKIP3: /* METAFONT never needs this */
if (do_output)
{
(void)(*outfcn)(c,max_n-n); /* output current row */
(void)clrrow(); /* clear next one */
}
--n; /* advance to next row below */
d = (unsigned int)nosignex(fontfp,(unsigned char)3); /* NOTE truncation */
if (do_output)
{
for (k = 0; k < d; (++k, --n)) /* output d white rows */
(void)(*outfcn)(c,max_n-n);
}
else
n -= (int)d;
m = min_m;
paint_switch = WHITE;
break;
case GFXXX1:
case GFXXX2:
case GFXXX3:
case GFXXX4:
case GFYYY:
case GFNOOP:
(void)ungetc((char)the_byte,fontfp);
(void)skgfspec();
break;
default:
if (((unsigned char)GFPAINT0 < the_byte) && (the_byte < GFPAINT1))
{
d = (unsigned int)(the_byte - GFPAINT0);
if (do_output && (paint_switch == BLACK))
{
for (k = 0; k < d; (++m, ++k))
SETBIT(m);
}
else
m += (int)d;
paint_switch = (unsigned char)(!paint_switch);
}
else if (((unsigned char)GFNROW0 <= the_byte) && (the_byte <= GFNROWMAX))
{
if (do_output)
{
(void)(*outfcn)(c,max_n-n); /* output current row */
(void)clrrow(); /* clear next one */
}
n--; /* advance to next row below */
paint_switch = BLACK;
m = min_m + (unsigned int)(the_byte - GFNROW0);
}
else
{
(void)sprintf(message,
"chargf(): Unexpected byte %d (0x%02x) in GF font file \
at position %ld",
the_byte,the_byte,(long)ftell(fontfp));
(void)warning(message);
return(EOF);
}
break;
} /* end switch */
the_byte = (unsigned char)nosignex(fontfp,(unsigned char)1);
} /* end for() */
}
/* This file departs from all others in the DVIxxx family in that it
declares some private functions and globals which are required nowhere
else. Only charpk() is called from outside. */
unsigned char get_bit(); /* return next bit from file */
unsigned char get_nybble(); /* return next 4-bit nybble from file */
unsigned int pk_packed_num(); /* get packed number from file */
unsigned char bit_weight; /* weight of current bit in next_byte */
unsigned char dyn_f; /* dynamic packing flag */
unsigned int repeat_count; /* how many times to repeat next row */
unsigned char next_byte; /* current input byte */
unsigned char word_weight; /* weight of current bit in *pword */
/**********************************************************************/
int charpk(c,outfcn) /* return 0 on success, and EOF on failure */
unsigned char c; /* current character value */
void (*outfcn)(); /* (possibly NULL) function to output current row */
{
int count; /* how many bits of current color left */
unsigned int c_width; /* character width in dots */
unsigned int c_height; /* character height in dots */
int do_output; /* FALSE if outfcn is NULL */
register unsigned char flag_byte; /* current file flag byte */
unsigned int h_bit; /* horizontal position in row */
register unsigned int i; /* loop index */
register unsigned int k; /* loop index */
long offset; /* offset into font file */
long p; /* pointer into font file */
unsigned long int packet_length; /* packet length */
unsigned long int* pword; /* pointer into img_row[] */
int rows_left; /* how many rows left */
struct char_entry *tcharptr;/* temporary char_entry pointer */
unsigned char turn_on; /* initial black/white flag */
/*******************************************************************
This function is called to process a single character description in
the PK font file. The character packet is pointed to by
fontptr->ch[c].fontrp, and was set by readpk(), which moved past any
special commands that precede the packet.
The PK raster description is encoded in a complex form, but is
guaranteed to step across raster rows from left to right, and down
from the top row to bottom row, such that in references to
image[n][m], m never decreases in a row, and n never increases in a
character. This means that we only require enough memory space to
hold one row, provided that outfcn(c,yoff) is called each time a row
is completed. This is an important economization for
high-resolution output devices -- e.g. a 10pt character at 2400
dots/inch would require about 8Kb for the entire image, but fewer
than 25 bytes for a single row. A 72pt character (such as in the
aminch font) would need about 430Kb for the image, but only about
200 bytes for a row.
The code follows PKtoPX quite closely, particular the latter's
sections 37-43 for preamble processing, and sections 44-51 for
raster decoding.
Access to bit m in the current row is controlled through the macros
SETBIT(m) and TESTBIT(m) so we need not be concerned about the
details of bit masking. Too bad C does not have a bit data type!
The row image is recorded in such a way that bits min_m .. max_m are
mapped onto bits 0 .. (max_m - min_m) in img_row[], so that
outfcn(c,yoff) should be relieved of any shifting operations.
outfcn(c,yoff) is NEVER called if either of hp or wp is <= 0, or if
it is NULL.
*******************************************************************/
if ((c < FIRSTPXLCHAR) || (LASTPXLCHAR < c))
{
(void)warning(
"charpk(): Character value out of range for PK font file");
return(EOF);
}
tcharptr = &(fontptr->ch[c]);
if (!VISIBLE(tcharptr))
return(0); /* empty character raster -- nothing to output */
c_width = (unsigned int)tcharptr->wp; /* local copies of these to save */
c_height = (unsigned int)tcharptr->hp; /* pointer dereferencing in loops */
p = (long)tcharptr->fontrp; /* font file raster pointer */
if (p < 0L)
{
(void)warning(
"charpk(): Requested character not found in PK font file");
return(EOF);
}
if (fseek(fontfp,p,0))
{
(void)warning(
"charpk(): fseek() failure for PK font file character raster");
return(EOF);
}
/* Since readpk() has already done error checking on the file, and
recorded the character metrics, we need not repeat that work, and
concentrate instead on getting to the encoded raster description
which follows the character packet. */
img_words = (unsigned int)(c_width + 31) >> 5;
flag_byte = (unsigned char)nosignex(fontfp,(unsigned char)1); /* get packet flag byte */
dyn_f = flag_byte >> 4; /* dyn_f is high 4 bits from flag_byte */
turn_on = (unsigned char)(flag_byte & 0x08); /* turn_on is 8-bit from flag_byte */
flag_byte &= 0x07; /* final flag_byte is low 3 bits */
do_output = (int)(outfcn != (void(*)())NULL);
switch(flag_byte) /* flag_byte is in 0..7 */
{
case 0:
case 1:
case 2:
case 3: /* short character preamble */
packet_length = (unsigned long int)flag_byte;
packet_length <<= 8;
packet_length += (unsigned long int)nosignex(fontfp,(unsigned char)1);
packet_length -= 8L;
offset = 9L;
break;
case 4:
case 5:
case 6: /* extended short character preamble */
packet_length = (unsigned long int)(flag_byte & 0x03);
packet_length <<= 16;
packet_length += (unsigned long int)nosignex(fontfp,(unsigned char)2);
packet_length -= 13L;
offset = 14L;
break;
case 7: /* long character preamble */
packet_length = (unsigned long int)nosignex(fontfp,(unsigned char)4);
packet_length -= 28L;
offset = 32L;
break;
} /* end switch */
if (fseek(fontfp,offset,1)) /* position to start of raster data */
{
(void)warning(
"charpk(): fseek() failure for PK font file character raster");
return(EOF);
}
bit_weight = 0;
if (dyn_f == (unsigned char)14) /* <PKtoPX: Get raster by bits> */
{ /* uncompressed character image */
for (i = 0; i < c_height; ++i)
{
pword = img_row;
if (do_output)
(void)clrrow();
word_weight = (unsigned char)31;
for (k = 0; k < c_width; ++k)
{
if (get_bit())
*pword |= power[word_weight];
if (word_weight)
--word_weight;
else
{
++pword;
word_weight = (unsigned char)31;
}
} /* end for (k) */
if (do_output)
(void)(*outfcn)(c,i);
} /* end for (i) */
}
else /* <PKtoPX: Create normally packed raster> */
{ /* run-length encoded character image */
rows_left = (int)c_height;
h_bit = c_width;
repeat_count = 0;
word_weight = (unsigned char)32;
pword = img_row;
if (do_output)
(void)clrrow(); /* clear img_row[] */
while (rows_left > 0)
{
count = (int)pk_packed_num();
while (count > 0)
{
if ( (count < (int)word_weight) && (count < (int)h_bit) )
{
if (turn_on)
{
*pword |= gpower[word_weight];
*pword &= ~gpower[word_weight - count];
}
h_bit -= (unsigned int)count;
word_weight -= (unsigned char)count;
count = 0;
}
else if ( (count >= (int)h_bit) &&
(h_bit <= (unsigned int)word_weight) )
{
if (turn_on)
{
*pword |= gpower[word_weight];
*pword &= ~gpower[word_weight - h_bit];
}
if (do_output)
{
for (i = 0; i <= repeat_count; (--rows_left, ++i))
(void)(*outfcn)(c,(unsigned int)(c_height-rows_left));
}
else
rows_left -= (int)(repeat_count + 1);
repeat_count = 0;
pword = img_row;
if (do_output)
(void)clrrow();
word_weight = (unsigned char)32;
count -= (int)h_bit;
h_bit = c_width;
}
else
{
if (turn_on)
*pword |= gpower[word_weight];
pword++;
count -= (int)word_weight;
h_bit -= (unsigned int)word_weight;
word_weight = (unsigned char)32;
}
} /* end while (count > 0) */
turn_on = (unsigned char)(!turn_on);
} /* end while (rows_left > 0) */
if ((rows_left > 0) || (h_bit != c_width))
{
(void)warning(
"charpk(): Bad PK font file--more bits than required");
return(EOF);
}
} /* end if (run-length encoded image) */
return(0);
}
unsigned char get_bit() /* return 0, or non-zero (not necessarily 1) */
{
register unsigned char temp;
bit_weight >>= 1;
if (bit_weight == 0) /* then must get new byte from font file */
{
next_byte = (unsigned char)nosignex(fontfp,(unsigned char)1);
bit_weight = (unsigned char)128;
}
temp = next_byte & bit_weight;
next_byte &= ~bit_weight; /* clear the just-read bit */
return (temp);
}
unsigned char get_nybble()
{
register unsigned char temp;
if (bit_weight == 0) /* get high nybble */
{
next_byte = (unsigned char)nosignex(fontfp,(unsigned char)1);
temp = next_byte >> 4;
next_byte &= 0x0f;
bit_weight = (unsigned char)1;
}
else /* get low nybble */
{
temp = next_byte; /* this has only 4 bits in it */
bit_weight = (unsigned char)0;
}
return(temp);
}
unsigned int pk_packed_num() /* return a (non-negative) packed number from the font file */
{ /* this function is recursive to one level only */
int i,j;
i = (int)get_nybble();
if (i == 0)
{
do
{
j = (int)get_nybble();
++i;
}
while (j == 0);
while (i > 0)
{
j <<= 4;
j += (int)get_nybble();
--i;
}
return((unsigned int)(j - 15 + ((13 - dyn_f) << 4) + dyn_f));
}
else if (i <= (int)dyn_f)
return((unsigned int)i);
else if (i < 14)
return((unsigned int)(((i - dyn_f - 1) << 4) + get_nybble() + dyn_f + 1));
else if (i == 14)
{
repeat_count = pk_packed_num();
return(pk_packed_num());
}
else
{
repeat_count = 1;
return(pk_packed_num());
}
}
int charpxl(c,outfcn) /* return 0 on success, and EOF on failure */
unsigned char c; /* current character value */
void (*outfcn)(); /* (possibly NULL) function to output current row */
{
unsigned int i,j; /* loop index */
long p; /* offset into font file */
register unsigned long int *q; /* pointer into rasters area */
struct char_entry *tcharptr;/* temporary char_entry pointer */
if ((c < FIRSTPXLCHAR) || (LASTPXLCHAR < c))
{
(void)warning(
"charpxl(): Character value out of range for PXL font file");
return(EOF);
}
tcharptr = &(fontptr->ch[c]);
if (!VISIBLE(tcharptr))
return(0); /* do nothing for empty characters */
p = (long)tcharptr->fontrp; /* font file raster pointer */
if (p < 0L)
{
(void)warning(
"charpxl(): Requested character not found in PXL font file");
return(EOF);
}
if (fseek(fontfp,p,0))
{
(void)warning(
"charpxl(): fseek() failure for PXL font file character raster");
return(EOF);
}
if (outfcn != (void(*)())NULL)
{
img_words = ((unsigned int)(tcharptr->wp) + 31) >> 5;
for (i = 0; i < (unsigned int)(tcharptr->hp); ++i)
{
q = img_row;
for (j = 0; j < img_words; ++j)
*q++ = (unsigned long int)nosignex(fontfp,(unsigned char)4);
(void)(*outfcn)(c,i);
}
}
return(0);
}
void clrrow() /* clear the current character image row, img_row[] */
{
register unsigned long int *p;
register unsigned int nwords;
nwords = img_words;
for (p = &img_row[nwords-1]; nwords; (--p,--nwords))
*p = (unsigned long int)0L;
}
void fillrect(x,y,width,height)
int x,y,width,height; /* lower left corner, size */
/***********************************************************************
With the page origin (0,0) at the lower-left corner of the bitmap, draw
a filled rectangle at (x,y).
***********************************************************************/
{
register unsigned long int *p;
register int i,j,xloffset,xroffset,xlpart,xrpart;
if ( ((x+width) <= 0) || (XSIZE <= x) || ((y+height) <= 0) ||
(YSIZE <= y) )
return; /* Trivial reject -- rectangle outside page */
else
{
xlpart = x/32;
xrpart = (x + width)/32;
xloffset = x % 32;
xroffset = (x + width) % 32;
for (j = 0; j < height; ++j) /* loop over raster lines */
{
if (IN(0,y+j,YBIT-1))
{
p = rd_bitmap(y+j,xlpart);
if (IN(0,xlpart,XBIT-1))
if (xlpart < xrpart) /* set bits in left partial word */
*p |= rightones[xloffset];
else /* set bits in middle of left partial word */
*p |= (rightones[xloffset] & ~rightones[xroffset]);
++p;
for (i = xlpart+1; i < xrpart; (++p,++i))
if (IN(0,i,XBIT-1))
*p = (unsigned long int)ONES; /* set complete words */
/* finally, set bits in right partial word */
if ((xlpart < xrpart) && IN(0,xrpart,XBIT-1))
*rd_bitmap(y+j,xrpart) |= ~rightones[xroffset];
}
}
}
}
void fontfile(filelist,font_path,font_name,magnification)
char *filelist[MAXFORMATS]; /* output filename list */
char *font_path; /* host font file pathname */
char *font_name; /* TeX font_name */
int magnification; /* magnification value */
{
/*
Given a TeX font_name and a magnification value, construct a list of
system-dependent host filenames, returning them in the first
argument. The files are not guaranteed to exist. The font names by
default contains names for the PK, GF, and PXL font files, but the
selection, and search order, may be changed at run time by defining
a value for the environment variable FONTLIST. See initglob() for
details.
*/
register int m; /* index into filelist[] */
register int k; /* loop index */
double fltdpi; /* dots/inch */
int dpi; /* dots/inch for filename */
/*
We need to convert an old-style ROUNDED integer magnification based
on 1000 units = 200 dpi to an actual rounded dpi value.
We have
magnification = round(real_mag) = trunc(real_mag + 0.5)
which implies
double(magnification) - 0.5 <= real_mag < double(magnification) + 0.5
We want
dpi = round(real_mag/5.0)
which implies
double(dpi) - 0.5 <= real_mag/5.0 < double(dpi) + 0.5
or
5.0*double(dpi) - 2.5 <= real_mag < 5.0*double(dpi) + 2.5
We can combine the two to conclude that
5.0*double(dpi) - 2.5 < double(magnification) + 0.5
or
5.0*double(dpi) - 3 < double(magnification)
which gives the STRICT inequality
double(dpi) < (double(magnification) + 3.0)/5.0
*/
fltdpi = (((double)magnification) + 3.0)/5.0;
dpi = (int)fltdpi;
if (fltdpi == (double)dpi)
dpi--; /* enforce inequality */
for (k = 0; k < MAXFORMATS; ++k) /* loop over possible file types */
*filelist[k] = '\0'; /* Initially, all filenames are empty */
m = 0; /* index in filelist[] */
for (k = 0; k < MAXFORMATS; ++k) /* loop over possible file types */
{
/* Typical results:
d:\tex\fonts\300\amr10.gf
d:\tex\fonts\300\amr10.pk
d:\tex\fonts\1500\amr10.pxl
*/
if (k == gf_index)
(void)sprintf(filelist[m++], "%s%d\\%s.gf",
font_path, dpi, font_name);
else if (k == pk_index)
(void)sprintf(filelist[m++], "%s%d\\%s.pk",
font_path, dpi, font_name);
else if (k == pxl_index)
(void)sprintf(filelist[m++], "%s%d\\%s.pxl",
font_path, magnification, font_name);
}
}
/***********************************************************************
Given a TeX fontname and a magnification value, search the font
substitution file (if any) for the first pattern defining a possible
replacement, and return their values in subfont[] and submag, with a
function value of TRUE. If no substitution is possible, subfont[] is
set to a null string, submag to 0, and the function value to FALSE.
The substitution file is searched for under the names
(1) subfile (by default, or from command line)
(2) subname subext
(3) subpath subname subext
allowing the user to have document-file specific substitutions, TeX-wide
private substitutions, and system TeX-wide substitutions. For example,
these files might be "sample.sub", "texfonts.sub", and
"texinputs:texfonts.sub" for a document "sample.tex".
Font substitution lines have the form:
% comment
oldname.oldmag -> subname.submag % comment
oldname oldmag -> subname submag % comment
oldname -> subname % comment
Examples are:
% These provide replacements for some LaTeX invisible fonts:
iamr10 1500 -> amr10 1500 % comment
iamr10.1500 -> amr10.1500 % comment
iamssb8 -> amssb8 % comment
These are easily readable by sscanf(). The first two forms request
substitution of a particular font and magnification. The third form
substitutes an entire font family; the closest available magnification
to the required one will be used. Any dots in the non-comment portion
will be converted to spaces, and therefore, cannot be part of a name
field.
The first matching substitution will be selected, so magnification-
specific substitutions should be given first, before family
substitutions.
Comments are introduced by percent and continue to end-of-line, just as
for TeX. One whitespace character is equivalent to any amount of
whitespace. Whitespace and comments are optional.
***********************************************************************/
int fontsub(subfont,submag,TeXfont,TeXmag)
char *subfont; /* new fontname returned */
int *submag; /* new magnification returned (0 if entire family) */
char *TeXfont; /* TeX requested fontname */
int TeXmag; /* TeX requested magnification value */
{
static FILE* subfp = (FILE *)NULL; /* file pointer for sub file */
static int have_file = TRUE; /* memory of open success */
char line[MAXSTR]; /* for sub file lines */
char *pline; /* pointer to line[] */
static char fname[64]; /* sub file name */
char oldfont[64]; /* working storage for font names */
int oldmag; /* font magnification */
int k; /* sscanf() result */
int line_number; /* for error messages */
if (!have_file) /* no file available */
{
*subfont = '\0';
*submag = 0;
return (FALSE);
}
else if (subfp == (FILE *)NULL) /* happens only first time */
{
(void)strcpy(fname,subfile); /* try document specific: */
subfp = fopen(fname,"r"); /* e.g. foo.sub (from foo.dvi) */
DEBUG_OPEN(subfp,fname,"r");
if (subfp == (FILE *)NULL)
{
(void)strcpy(fname,subname);/* try path specific: */
(void)strcat(fname,subext); /* e.g. texfonts.sub */
subfp = fopen(fname,"r");
DEBUG_OPEN(subfp,fname,"r");
}
if (subfp == (FILE *)NULL)
{
(void)strcpy(fname,subpath);/* try system specific: */
(void)strcat(fname,subname);/* e.g. texinputs:texfonts.sub */
(void)strcat(fname,subext);
subfp = fopen(fname,"r");
DEBUG_OPEN(subfp,fname,"r");
}
if (subfp == (FILE *)NULL) /* could not open any substitution file */
{
have_file = FALSE;
*subfont = '\0';
*submag = 0;
return (FALSE);
}
}
line_number = 0;
(void)rewind(subfp);
while (fgets(line,MAXSTR,subfp) != (char *)NULL)
{
line_number++; /* count lines */
pline = &line[0]; /* truncate at comment start or end-of-line */
while ((*pline) && (*pline != '%') &&
(*pline != '\r') && (*pline != '\n'))
{
if (*pline == '.') /* convert dots to whitespace for sscanf() */
*pline = ' ';
++pline;
}
*pline = '\0'; /* replace terminator by NUL */
if ((k = (int)sscanf(line," %s %d -> %s %d",oldfont,&oldmag,
subfont,submag)) == 4)
{
if ((TeXmag == oldmag) && (stricmp(oldfont,TeXfont) == 0))
return (TRUE);
}
else if ((k = (int)sscanf(line," %s -> %s",oldfont,subfont)) == 2)
{
*submag = 0;
if (stricmp(oldfont,TeXfont) == 0)
return (TRUE);
}
else if (k != EOF) /* EOF means no fields, so have empty line */
{
(void)sprintf(message,
"fontsub(): Bad font substitution at line %d in file \
[%s]: [%s]",
line_number,fname,line);
(void)warning(message);
}
}
*subfont = '\0';
*submag = 0;
return (FALSE);
}
/***********************************************************************
Read the font definitions as they are in the postamble of the DVI file.
Note that the font directory is not yet loaded.
***********************************************************************/
void getfntdf()
{
register unsigned char byte;
while (((byte = (unsigned char)nosignex(dvifp,(unsigned char)1)) >= FNT_DEF1)
&& (byte <= FNT_DEF4))
readfont ((long int)nosignex(dvifp,(unsigned char)(byte-FNT_DEF1+1)));
if (byte != POST_POST)
(void)fatal ("getfntdf(): POST_POST missing after fontdefs");
}
void getpgtab(lastpageptr)
long lastpageptr;
{
register long p;
register int i,k;
(void) fseek (dvifp,lastpageptr,0);
p = lastpageptr;
for (k = 0; (p != (-1)) && (k < MAXPAGE); ++k)
{
page_ptr[MAXPAGE-1-k] = p;
(void) fseek (dvifp,(long) p, 0);
if ((unsigned char)nosignex(dvifp,(unsigned char)1) != BOP)
(void)fatal(
"getpgtab(): Invalid BOP (beginning-of-page) back chain");
for (i = 0; i <= 9; ++i)
(void) nosignex(dvifp,(unsigned char)4); /* discard count0..count9 */
p = (long)signex(dvifp,(unsigned char)4);
}
page_count = k;
if (k >= MAXPAGE)
(void)warning("getpgtab(): Page table full...rebuild driver with \
larger MAXPAGE");
else /* move pointer table to front of array */
for (k = 0; k < page_count; ++k)
page_ptr[k] = page_ptr[MAXPAGE-page_count+k];
}
/***********************************************************************
Convert a value field in s[] of the form
------ ------------------------------
value units implied
------ ------------------------------
#.##bp big point (1in = 72bp)
#.##cc cicero (1cc = 12dd)
#.##cm centimeter
#.##dd didot point (1157dd = 1238pt)
#.##in inch
#.##mm millimeter (10mm = 1cm)
#.##pc pica (1pc = 12pt)
#.##pt point (72.27pt = 1in)
#.##sp scaled point (65536sp = 1pt)
------ ------------------------------
to inches, returning it as the function value. A leading plus or minus
sign is optional. The letter case of the dimension name is ignored. No
space is permitted between the number and the dimension.
***********************************************************************/
double inch(char *s)
{
int neg;
register char *tc;
register double flnum, pten;
flnum = 0.0;
tc = s;
neg = FALSE;
if (*tc == '-')
{
++tc;
neg = TRUE;
}
else if (*tc == '+')
{
++tc;
neg = FALSE;
}
/* we do not use sprintf() here because we want to be able to easily
find the dimension string */
for (; isdigit(*tc); ++tc) /* collect integer part */
flnum = flnum*10.0 + (double)((*tc) - '0');
if (*tc == '.') /* collect fractional part */
for ((pten = 10.0, ++tc); isdigit(*tc); (pten *= 10.0,++tc))
flnum += ((double)((*tc) - '0'))/pten;
if (stricmp(tc,"in") == 0) /* inches */
;
else if (stricmp(tc,"cm") == 0) /* centimeters */
flnum /= 2.54;
else if (stricmp(tc,"pt") == 0) /* points */
flnum /= 72.27;
else if (stricmp(tc,"bp") == 0) /* big points */
flnum /= 72.0;
else if (stricmp(tc,"cc") == 0) /* cicero */
flnum *= 12.0 * (1238.0 / 1157.0) / 72.27;
else if (stricmp(tc,"dd") == 0) /* didot points */
flnum *= (1238.0 / 1157.0) / 72.27;
else if (stricmp(tc,"mm") == 0) /* millimeters */
flnum /= 25.4;
else if (stricmp(tc,"pc") == 0) /* pica */
flnum *= 12.0 / 72.27;
else if (stricmp(tc,"sp") == 0) /* scaled points */
flnum /= (65536.0 * 72.27);
else /* unknown units -- error */
#if PXLID /* must be in DVI driver */
{
(void)sprintf(message,
"inch(): Unrecognized dimension string [%s];\nexpected one of \
bp, cc, cm, dd, in, mm, pc, pt or sp\n",s);
(void)fatal(message);
}
#else /* some other program then */
{
(void)fprintf(stderr,"inch(): Unrecognized dimension string [%s];",s);
NEWLINE(stderr);
(void)fprintf(stderr,
"expected one of bp, cc, cm, dd, in, mm, pc, pt or sp");
NEWLINE(stderr);
exit(1);
}
#endif
if (neg)
flnum = -flnum;
return((double)flnum);
}
/***********************************************************************
This simple version will do for now. Even in a book DVI file, there
are unlikely to be more than about 25 fonts used and with an average
of 50 characters each, this is about 1250 character definitions.
With typical character sizes of 10 point type on a 300 dots/inch
device, each would take a block of (10/72)*300 = 42 dots square, or
about 84 words each, for a total storage requirement of 84*1250 =
105000 words. This is quite reasonable for the DEC-20/60 and VAX
Unix implementations, and may be acceptable on large memory
microprocessors like the MC68000 and NS16000.
However, for future expansion, a reference count of each character
is maintained, and the total storage allocated for character
descriptions is recorded. Then, when malloc fails, or MAXCACHE is
reached, the font entries can be scanned to find the least used
characters whose raster storage can then be freed and malloc
retried.
***********************************************************************/
void loadchar(unsigned char c)
{
void (*charyy)(); /* subterfuge to get around PCC-20 bug */
register unsigned long int nwords; /* how many 32-bit words we need */
register struct char_entry *tcharptr;
if ((c < FIRSTPXLCHAR) || (LASTPXLCHAR < c)) /* check character range */
return;
tcharptr = &(fontptr->ch[c]);
if (!VISIBLE(tcharptr)) /* check for empty character rasters */
return;
nwords = (unsigned long int)(((tcharptr->wp+31) >> 5) * (tcharptr->hp));
tcharptr->rasters = (unsigned long int*)malloc((unsigned)(nwords*sizeof(unsigned long int)));
if (tcharptr->rasters == (unsigned long int*)NULL)
{
(void)sprintf(message,"loadchar(): Could not allocate %ld words of \
raster space--used %ld words so far",
(long)nwords,(long)cache_size);
(void)fatal(message);
}
tcharptr->refcount = 0; /* clear reference count */
cache_size += (long int)nwords; /* update cache size record */
if (fontptr != pfontptr)
openfont(fontptr->n);
if (fontfp == (FILE *)NULL) /* do nothing if no font file */
return;
/* Bug workaround: PCC-20 otherwise jumps to charxx instead of *charxx */
charyy = fontptr->charxx;
(void)(*charyy)(c,outrow); /* load character from font file */
}
/* From DVITYPE Version 2.6:
"Vertical motion is done similarly [to horizontal motion handled
in moveover()], but with the threshold between ``small'' and
``large'' increased by a factor of five. The idea is to make
fractions like ``1/2'' round consistently, but to absorb
accumulated rounding errors in the baseline-skip moves."
The one precaution we need to take here is that fontptr can be
NULL, which we treat like a large movement. This NULL pointer
was used without error on many different machines for 2 years
before it was caught on the VAX VMS implementation, which makes
memory page 0 inaccessible.
*/
void movedown(a)
register long int a;
{
v += a;
if ((fontptr == (struct font_entry *)NULL) ||
(ABS(a) >= 5*fontptr->font_space))
vv = PIXROUND(v, conv * ((double)YDPI/(double)XDPI)) + tmargin;
else
{
vv += PIXROUND(a, conv * ((double)YDPI/(double)XDPI));
vv = fixpos(vv-tmargin, v,
conv * ((double)YDPI/(double)XDPI)) + tmargin;
}
}
/* From DVITYPE Version 2.6:
"Rounding to the nearest pixel is best done in the manner shown
here, so as to be inoffensive to the eye: When the horizontal
motion is small, like a kern, |hh| changes by rounding the kern;
but when the motion is large, |hh| changes by rounding the true
position |h| so that accumulated rounding errors disappear. We
allow a larger space in the negative direction than in the
positive one, because TeX makes comparatively large backspaces
when it positions accents."
The one precaution we need to take here is that fontptr can be
NULL, which we treat like a large movement. This NULL pointer
was used without error on many different machines for 2 years
before it was caught on the VAX VMS implementation, which makes
memory page 0 inaccessible.
*/
void moveover(b)
register long int b;
{
h += b;
if ((fontptr == (struct font_entry *)NULL) ||
ABS(b) >= fontptr->font_space)
hh = PIXROUND(h, conv) + lmargin;
else
{
hh += PIXROUND(b, conv);
hh = fixpos(hh-lmargin,h,conv) + lmargin;
}
}
void moveto(x,y)
int x,y;
{
xcp = x;
ycp = y;
}
unsigned long int nosignex(fp, n) /* return n byte quantity from file fd */
register FILE *fp; /* file pointer */
register unsigned char n; /* number of bytes (1..4) */
{
register unsigned long int number; /* number being constructed */
number = 0;
while (n--)
{
number <<= 8;
number |= getc(fp);
}
return((unsigned long int)number);
}
/***********************************************************************
The original version of this DVI driver reopened the font file each
time the font changed, resulting in an enormous number of relatively
expensive file openings. This version keeps a cache of up to
MAXOPEN open files, so that when a font change is made, the file
pointer, fontfp, can usually be updated from the cache. When the
file is not found in the cache, it must be opened. In this case,
the next empty slot in the cache is assigned, or if the cache is
full, the least used font file is closed and its slot reassigned for
the new file. Identification of the least used file is based on the
counts of the number of times each file has been "opened" by this
routine. On return, the file pointer is always repositioned to the
beginning of the file.
If the first open attempt fails, an attempt will be made to use a
substitute font, then neighboring magnifications (with the same font
name), or substitutes for them.
***********************************************************************/
void openfont(fontname)
char *fontname;
{
register int i,j,k; /* loop indices */
int current;
int least_used;
int maxopen = MAXOPEN;
struct font_entry *tfontptr;
char subfont[64];
int submag;
char* filelist[MAXFORMATS]; /* pointers to templist[][] */
char templist[MAXFORMATS][64];
#if VIRTUAL_FONTS
struct stat statbuf; /* so fstat() can get file size */
char *p;
#endif
if ((pfontptr != (struct font_entry *)NULL) && (pfontptr == fontptr))
return; /* we need not have been called */
for (j = 0; j < MAXFORMATS; ++j) /* initialize fontlist pointers */
filelist[j] = &templist[j][0];
for (current = 1;
(current <= nopen) &&
(font_files[current].font_id != fontptr->font_file_id);
++current)
; /* try to find file in open list */
if (current <= nopen) /* file already open, lookup its id */
fontfp = font_files[current].font_id;
else
{
/***************************************************************
The file was not in list of open files. If the list is not
full, add it to the list; otherwise close the least-used file
and remove it from the font_entry containing it. Finally, open
the file, or its closest neighbor in the magnification family.
A warning is issued if no file can be opened. The caller can
then proceed with zero font metrics if desired.
***************************************************************/
if (nopen < maxopen) /* just add it to list */
current = ++nopen;
else /* list full -- find least used file, */
{ /* close it, and reuse slot for new file */
least_used = 1;
for (i = 2; i <= maxopen; ++i)
if (font_files[least_used].use_count >
font_files[i].use_count)
least_used = i;
fontfp = font_files[least_used].font_id;
tfontptr = hfontptr;
while (tfontptr != (struct font_entry*)NULL)
{ /* remove file pointer from its font_entry */
if (tfontptr->font_file_id == fontfp)
{
tfontptr->font_file_id = (FILE*)NULL;
break;
}
tfontptr = tfontptr->next;
}
#if VIRTUAL_FONTS
if (virt_font && (fontfp != (FILE*)NULL))
(void)virtfree(fontfp);
#endif
(void)fclose(fontfp);
fontfp = (FILE*)NULL;
current = least_used;
}
(void)actfact(fontptr->font_mag); /* Get global mag_index */
fontfp = (FILE*)NULL;
/***************************************************************
Try the requested font, then any substitute font, then for each
neighboring magnification from nearest to furthest, try the
requested font, and then any substitute font.
***************************************************************/
for (k = 0; (fontfp == (FILE*)NULL) && (k < MAGTABSIZE); ++k)
{ /* loop over mag family */
for (i = -k; (fontfp == (FILE*)NULL) && (i <= k); i += MAX(1,k+k))
{ /* try smaller, then larger */
if (IN(0,mag_index+i,MAGTABSIZE-1))
{
(void)fontfile(filelist, ((fontptr->a==0)?fontpath:""),
fontname, (int)MAGSIZE(mag_table[mag_index+i]));
for (j = 0; (j < MAXFORMATS) && *filelist[j]; ++j)
{
fontfp = fopen(filelist[j],"rb");
DEBUG_OPEN(fontfp,filelist[j],"rb");
if (fontfp != (FILE *)NULL)
{
strcpy(fontptr->name,filelist[j]);
break;
}
}
if ((k > 0) && (fontfp != (FILE*)NULL))
{
(void)sprintf(message,
"Font file [%s [mag %d]] could not be opened.\n\
---using nearest neighbor [%s [mag %d]] instead.",
fontname,(int)MAGSIZE(mag_table[mag_index]),
fontptr->name,
(int)MAGSIZE(mag_table[mag_index+i]));
(void)warning(message);
}
if ((fontfp == (FILE*)NULL) && fontsub(subfont,&submag,
fontname,(int)MAGSIZE(mag_table[mag_index+i])))
{
(void)fontfile(filelist,((fontptr->a==0)?fontpath:""),
subfont,(submag ? submag :
(int)MAGSIZE(mag_table[mag_index+i])));
for (j = 0; (j < MAXFORMATS) && *filelist[j]; ++j)
{
fontfp = fopen(filelist[j],"rb");
DEBUG_OPEN(fontfp,filelist[j],"rb");
if (fontfp != (FILE *)NULL)
{
strcpy(fontptr->name,filelist[j]);
break;
}
}
if (fontfp != (FILE*)NULL)
{
(void)sprintf(message,
"Substituting font file [%s [mag %d]] \
by [%s [mag %d]]",
fontname,(int)MAGSIZE(mag_table[mag_index]),
fontptr->name,
(int)MAGSIZE(mag_table[mag_index+i]));
(void)warning(message);
}
}
}
} /* end for (i) -- loop over smaller and larger neighbors */
} /* end for (k) -- loop over mag family */
if (fontfp == (FILE*)NULL)
{
--nopen; /* don't count this failed open */
(void)sprintf(message,"Font file [%s [mag %d]] could not be \
opened; %d font files are open\n\
Proceeding with zero size characters for this font",
fontname,(int)MAGSIZE(mag_table[mag_index]),nopen);
(void)warning(message);
}
font_files[current].font_id = fontfp;
font_files[current].use_count = 0;
#if VIRTUAL_FONTS
/*
****************************************************************
This code is implementation-dependent. On many C compilers,
FILE points to a struct of the form
struct _iobuf {
char *_ptr; // pointer to next available char
int _cnt; // number of chars left in buffer
char *_base; // pointer to start of buffer
int _flag; // assorted flags
int _file; // file number handle
}
To implement virtual fonts, we save the pointers in a private
global array, get the file size from fstat(), malloc() a buffer
for it, read the entire file in, and replace the pointers in the
FILE variable with ones for the new buffer. Just before the
file is closed, the space is freed and the old pointers are
restored. Although many C implementations use malloc() to get
the buffer space in the first place, which would make this
saving unnecessary, not all do; see the implementation given in
Kernighan and Ritchie "The C Programming Language", p. 168.
In implementing this code on any new machine, the
implementations of fread(), read(), fseek(), and rewind() should
be checked to choose the most efficient one (e.g. one system
call for entire file read, and no double buffering), and make
sure that fseek() and rewind() do not unnecessarily discard
input buffer contents. fseek() and rewind() are defined in
terms of macros FSEEK() and REWIND() in machdefs.h to facilitate
replacement.
****************************************************************
*/
if (virt_font)
{
virt_save[fileno(fontfp)].base = (char *)NULL;
(void)fstat(fileno(fontfp),&statbuf); /* get file size */
p = (char *)malloc((int)statbuf.st_size); /* get file buffer */
if (p != (char *)NULL)
{
if (read(fileno(fontfp),p,(int)statbuf.st_size)
== (int)statbuf.st_size)
{ /* read successful */
virt_save[fileno(fontfp)].ptr = FILE_PTR(fontfp);
virt_save[fileno(fontfp)].cnt = FILE_CNT(fontfp);
virt_save[fileno(fontfp)].base = FILE_BASE(fontfp);
FILE_PTR(fontfp) = p;
FILE_BASE(fontfp) = p;
FILE_CNT(fontfp) = (int)statbuf.st_size;
}
else /* failure */
{
(void)rewind(fontfp);
(void)free(p); /* free dynamic buffer */
}
}
if (DBGOPT(DBG_FONT_CACHE))
{
(void)fprintf(stderr,"\nopenfont(): Font file %d [%s] ",
(int)fileno(fontfp),fontptr->name);
if (p == (char *)NULL)
(void)fprintf(stderr,
"cannot callocate buffer for entire file\n");
else
(void)fprintf(stderr,
"buffer length 0x%x\told buffer at 0x%lx\t\
new buffer at 0x%lx\n",
(int)statbuf.st_size,
(long)virt_save[fileno(fontfp)].base,
(long)FILE_BASE(fontfp));
}
}
#endif
} /* end if (file is in open list) */
pfontptr = fontptr; /* make previous = current font */
fontptr->font_file_id = fontfp; /* set file identifier */
font_files[current].use_count++; /* update reference count */
}
#if VIRTUAL_FONTS
void virtfree(fp) /* free buffer space before close */
FILE *fp;
{
if (virt_font && (fp != (FILE*)NULL) &&
(virt_save[fileno(fp)].base != (char *)NULL))
{
(void)fflush(fp);
(void)free(FILE_BASE(fp));
FILE_PTR(fp) = virt_save[fileno(fp)].ptr;
FILE_CNT(fp) = virt_save[fileno(fp)].cnt;
FILE_BASE(fp) = virt_save[fileno(fp)].base;
virt_save[fileno(fp)].base = (char *)NULL;
}
}
#endif
void readfont(long int font_k)
{
unsigned char a, l;
unsigned long int c; /* checksum */
unsigned long int d; /* design size */
char n[MAXSTR];
unsigned long int s; /* scale factor */
struct font_entry *tfontptr; /* temporary font_entry pointer */
c = nosignex(dvifp,(unsigned char)4);
s = nosignex(dvifp,(unsigned char)4);
d = nosignex(dvifp,(unsigned char)4);
a = (unsigned char)nosignex(dvifp,(unsigned char)1);
l = (unsigned char)nosignex(dvifp,(unsigned char)1);
(void)getbytes(dvifp, n, (unsigned char)(a+l));
n[a+l] = '\0';
tfontptr = (struct font_entry*)malloc((unsigned)sizeof(struct font_entry));
if (tfontptr == (struct font_entry *)NULL)
(void)fatal(
"readfont(): No allocable memory space left for font_entry");
tfontptr->next = hfontptr;
fontptr = hfontptr = tfontptr;
fontptr->k = font_k;
fontptr->c = c;
fontptr->s = s;
fontptr->d = d;
fontptr->a = a;
fontptr->l = l;
(void)strcpy(fontptr->n, n);
fontptr->font_space = (long int)(s/6);
(void)reldfont(fontptr);
}
int readgf() /* return 0 on success, EOF on failure */
{
unsigned long int checksum;
register struct char_entry *tcharptr;/* temporary char_entry pointer */
register unsigned char the_byte;
register unsigned int the_char; /* loop index */
/*
Read a GF file postamble, extracting character metrics and raster
locations. The character xoffp, yoffp, wp, and hp values will not
be filled in until a character raster description is actually called
for.
*/
/******************************************************************/
/* Process the post-postamble */
if (fseek(fontfp,-4L,2)) /* start 4 bytes from end-of-file */
{
(void)warning("readgf(): fseek() failed--GF font file may be empty");
return(EOF);
}
while ((the_byte = (unsigned char)nosignex(fontfp,(unsigned char)1)) == GFEOF)
{
if (fseek(fontfp,-2L,1))/* backup 2 bytes to read previous one */
{
(void)warning(
"readgf(): fseek() failed to find GF font file EOF trailer bytes");
return(EOF);
}
}
if (the_byte != (unsigned char)GFID)
{
(void)warning("readgf(): GF font file ID byte not found");
return(EOF);
}
if (fseek(fontfp,-6L,1)) /* backup to read post_post */
{
(void)warning(
"readgf(): fseek() failed to find GF font file POSTPOST byte");
return(EOF);
}
if ((unsigned char)nosignex(fontfp,(unsigned char)1) != (unsigned char)GFPOSTPOST)
{
(void)warning("readgf(): GF font file POSTPOST byte not found");
return(EOF);
}
if (fseek(fontfp,(long)nosignex(fontfp,(unsigned char)4),0))
{ /* position to start of postamble */
(void)warning(
"readgf(): fseek() failed to find postamble in GF font file");
return(EOF);
}
/******************************************************************/
/* Process the postamble */
if ((unsigned char)nosignex(fontfp,(unsigned char)1) != (unsigned char)GFPOST)
{
(void)warning("readgf(): GF font file POST byte not found");
return(EOF);
}
(void)nosignex(fontfp,(unsigned char)4); /* discard special pointer p[4] */
fontptr->designsize = nosignex(fontfp,(unsigned char)4);
checksum = nosignex(fontfp,(unsigned char)4);
if ((fontptr->c != 0L) && (checksum != 0L) && (fontptr->c != checksum))
{
(void)sprintf(message,
"readgf(): font [%s] has checksum = 10#%010lu [16#%08lx] [8#%011lo] \
different from DVI checksum = 10#%010lu [16#%08lx] [8#%011lo]. \
TeX preloaded .fmt file is probably out-of-date with respect to new fonts.",
fontptr->name, fontptr->c, fontptr->c, fontptr->c,
checksum, checksum, checksum);
(void)warning(message);
}
fontptr->hppp = (unsigned long int)nosignex(fontfp,(unsigned char)4);
fontptr->vppp = (unsigned long int)nosignex(fontfp,(unsigned char)4);
fontptr->min_m = (long int)signex(fontfp,(unsigned char)4);
fontptr->max_m = (long int)signex(fontfp,(unsigned char)4);
fontptr->min_n = (long int)signex(fontfp,(unsigned char)4);
fontptr->max_n = (long int)signex(fontfp,(unsigned char)4);
fontptr->magnification = (unsigned long int)( 0.5 + 5.0 * 72.27 *
(double)(fontptr->hppp) / 65536.0 ); /* from GFtoPXL Section 53 */
/******************************************************************/
/* Process the character locators */
the_byte = (unsigned char)GFNOOP;
while (the_byte == (unsigned char)GFNOOP)
{
switch(the_byte = (unsigned char)nosignex(fontfp,(unsigned char)1))
{
case GFCHLOC:
case GFCHLOC0:
the_char = (unsigned int)nosignex(fontfp,(unsigned char)1);
/* character number MOD 256 */
if (the_char >= NPXLCHARS)
{
(void)warning(
"readgf(): GF font file character number is too big for me");
return(EOF);
}
tcharptr = &(fontptr->ch[the_char]);
if (the_byte == (unsigned char)GFCHLOC) /* long form */
{
tcharptr->dx = (long int)signex(fontfp,(unsigned char)4);
tcharptr->dy = (long int)signex(fontfp,(unsigned char)4);
}
else /* short form */
{
tcharptr->dx = (long int)(((unsigned long int)nosignex(fontfp,(unsigned char)1)) <<
16);
tcharptr->dy = 0L;
}
tcharptr->tfmw = (unsigned long int)(((double)nosignex(fontfp,(unsigned char)4) *
(double)fontptr->s) / (double)(1L << 20));
tcharptr->pxlw = (unsigned int)PIXROUND(tcharptr->dx, 1.0/65536.0);
tcharptr->fontrp = (long)signex(fontfp,(unsigned char)4);
the_byte = (unsigned char)GFNOOP; /* to force loop continuation */
break;
case GFNOOP:
break;
default: /* this causes loop exit */
break;
} /* end switch */
} /* end while */
for (the_char = FIRSTPXLCHAR; the_char <= LASTPXLCHAR; the_char++)
{ /* Get remaining character metrics, and ignore error returns for now. */
tcharptr = &(fontptr->ch[the_char]);
if (tcharptr->fontrp >= 0L)
(void)chargf((unsigned char)the_char,(void(*)())NULL);
}
return(0);
}
int readpk() /* return 0 on success, EOF on failure */
{
unsigned long int checksum;
long end_of_packet; /* pointer to byte following character packet */
register unsigned char flag_byte;
unsigned long int packet_length;
long start_of_packet; /* pointer to start of character packet */
register struct char_entry *tcharptr;/* temporary char_entry pointer */
register unsigned long int the_char;
/* Read a PK file, extracting character metrics and raster
locations. */
/******************************************************************/
/* Process the preamble parameters */
(void)rewind(fontfp); /* start at beginning of file */
if ((unsigned char)nosignex(fontfp,(unsigned char)1) != PKPRE)
{
(void)warning("readpk(): PK font file does not start with PRE byte");
return(EOF);
}
if ((unsigned char)nosignex(fontfp,(unsigned char)1) != PKID)
{
(void)warning(
"readpk(): PK font file PRE byte not followed by ID byte");
return(EOF);
}
if (fseek(fontfp,(long)nosignex(fontfp,(unsigned char)1),1))
{
(void)warning("readpk(): PK font file has garbled comment string");
return(EOF); /* skip comment string */
}
fontptr->designsize = nosignex(fontfp,(unsigned char)4);
checksum = nosignex(fontfp,(unsigned char)4); /* checksum */
if ((fontptr->c != 0L) && (checksum != 0L) && (fontptr->c != checksum))
{
(void)sprintf(message,
"readpk(): font [%s] has checksum = 10#%010lu [16#%08lx] [8#%011lo] \
different from DVI checksum = 10#%010lu [16#%08lx] [8#%011lo]. \
TeX preloaded .fmt file is probably out-of-date with respect to new fonts.",
fontptr->name, fontptr->c, fontptr->c, fontptr->c,
checksum, checksum, checksum);
(void)warning(message);
}
fontptr->hppp = (unsigned long int)nosignex(fontfp,(unsigned char)4);
fontptr->vppp = (unsigned long int)nosignex(fontfp,(unsigned char)4);
fontptr->min_m = 0L; /* these are unused in PK format */
fontptr->max_m = 0L;
fontptr->min_n = 0L;
fontptr->max_n = 0L;
fontptr->magnification = (unsigned long int)( 0.5 + 5.0 * 72.27 *
(double)(fontptr->hppp) / 65536.0 ); /* from GFtoPXL Section 53 */
/******************************************************************/
/* Process the characters until the POST byte is reached */
(void)skpkspec(); /* skip any PK specials */
start_of_packet = (long)ftell(fontfp);
while ((flag_byte = (unsigned char)nosignex(fontfp,(unsigned char)1)) != PKPOST)
{
flag_byte &= 0x07;
switch(flag_byte) /* flag_byte is in 0..7 */
{
case 0:
case 1:
case 2:
case 3: /* short character preamble */
packet_length = (unsigned long int)flag_byte;
packet_length <<= 8;
packet_length += (unsigned long int)nosignex(fontfp,(unsigned char)1);
the_char = (unsigned long int)nosignex(fontfp,(unsigned char)1);
if (the_char >= NPXLCHARS)
{
(void)warning(
"readpk(): PK font file character number is too big for me");
return(EOF);
}
tcharptr = &(fontptr->ch[the_char]);
end_of_packet = (long)ftell(fontfp) + (long)packet_length;
tcharptr->tfmw = (unsigned long int)(((double)nosignex(fontfp,(unsigned char)3) *
(double)fontptr->s) / (double)(1L << 20));
tcharptr->dx = (long int)nosignex(fontfp,(unsigned char)1) << 16;
tcharptr->dy = 0L;
tcharptr->pxlw = (unsigned int)PIXROUND(tcharptr->dx, 1.0/65536.0);
tcharptr->wp = (int)nosignex(fontfp,(unsigned char)1);
tcharptr->hp = (int)nosignex(fontfp,(unsigned char)1);
tcharptr->xoffp = (int)signex(fontfp,(unsigned char)1);
tcharptr->yoffp = (int)signex(fontfp,(unsigned char)1);
break;
case 4:
case 5:
case 6: /* extended short character preamble */
packet_length = (unsigned long int)(flag_byte & 0x03);
packet_length <<= 16;
packet_length += (unsigned long int)nosignex(fontfp,(unsigned char)2);
the_char = (unsigned long int)nosignex(fontfp,(unsigned char)1);
if (the_char >= NPXLCHARS)
{
(void)warning(
"readpk(): PK font file character number is too big for me");
return(EOF);
}
tcharptr = &(fontptr->ch[the_char]);
end_of_packet = (long)ftell(fontfp) + (long)packet_length;
tcharptr->tfmw = (unsigned long int)(((double)nosignex(fontfp,(unsigned char)3) *
(double)fontptr->s) / (double)(1L << 20));
tcharptr->dx = (long int)nosignex(fontfp,(unsigned char)2) << 16;
tcharptr->dy = 0L;
tcharptr->pxlw = (unsigned int)PIXROUND(tcharptr->dx, 1.0/65536.0);
tcharptr->wp = (int)nosignex(fontfp,(unsigned char)2);
tcharptr->hp = (int)nosignex(fontfp,(unsigned char)2);
tcharptr->xoffp = (int)signex(fontfp,(unsigned char)2);
tcharptr->yoffp = (int)signex(fontfp,(unsigned char)2);
break;
case 7: /* long character preamble */
packet_length = (unsigned long int)nosignex(fontfp,(unsigned char)4);
the_char = (unsigned long int)nosignex(fontfp,(unsigned char)4);
if (the_char >= NPXLCHARS)
{
(void)warning(
"readpk(): PK font file character number is too big for me");
return(EOF);
}
tcharptr = &(fontptr->ch[the_char]);
end_of_packet = (long)ftell(fontfp) + (long)packet_length;
tcharptr->tfmw = (unsigned long int)(((double)nosignex(fontfp,(unsigned char)4) *
(double)fontptr->s) / (double)(1L << 20));
tcharptr->dx = (long int)signex(fontfp,(unsigned char)4);
tcharptr->dy = (long int)signex(fontfp,(unsigned char)4);
tcharptr->pxlw = (unsigned int)PIXROUND(tcharptr->dx, 1.0/65536.0);
tcharptr->wp = (int)nosignex(fontfp,(unsigned char)4);
tcharptr->hp = (int)nosignex(fontfp,(unsigned char)4);
tcharptr->xoffp = (int)signex(fontfp,(unsigned char)4);
tcharptr->yoffp = (int)signex(fontfp,(unsigned char)4);
break;
} /* end switch */
tcharptr->fontrp = start_of_packet;
(void)fseek(fontfp,end_of_packet,0); /* position to end of packet */
(void)skpkspec(); /* skip any PK specials */
start_of_packet = (long)ftell(fontfp);
} /* end while */
return(0);
}
/***********************************************************************
This routine is used to read in the postamble values. It initializes
the magnification and checks the stack height prior to starting printing
the document.
***********************************************************************/
void readpost()
{
long lastpageptr; /* byte pointer to last physical page */
int the_page_count; /* page count from DVI file */
findpost();
if ((unsigned char)nosignex(dvifp,(unsigned char)1) != POST)
(void)fatal("readpost(): POST missing at head of postamble");
lastpageptr = (long)nosignex(dvifp,(unsigned char)4);
num = nosignex(dvifp,(unsigned char)4);
den = nosignex(dvifp,(unsigned char)4);
mag = nosignex(dvifp,(unsigned char)4);
conv = ((double)num/(double)den) *
((double)runmag/(double)STDMAG) *
actfact(mag) *
((double)RESOLUTION/254000.0);
/* denominator/numerator here since will be dividing by the conversion
factor */
(void) nosignex(dvifp,(unsigned char)4); /* height-plus-depth of tallest page */
(void) nosignex(dvifp,(unsigned char)4); /* width of widest page */
if ((int)nosignex(dvifp,(unsigned char)2) >= STACKSIZE)
(void)fatal("readpost(): Stack size is too small");
the_page_count = (int)nosignex(dvifp,(unsigned char)2);
if (!quiet)
{
(void)fprintf(stderr,"[%d pages]",the_page_count);
NEWLINE(stderr);
(void)fprintf(stderr,"[%d magnification]",(int)runmag);
NEWLINE(stderr);
}
if (preload)
getfntdf();
getpgtab(lastpageptr);
}
int readpxl() /* return 0 on success, EOF on failure */
{
unsigned long int checksum;
register struct char_entry *tcharptr;/* temporary char_entry pointer */
register unsigned int the_char; /* loop index */
if (fseek(fontfp,-20L,2)) /* 20 bytes before end-of-file for checksum */
{
(void)warning("readpxl(): fseek() failed--PXL font file may be empty");
return(EOF);
}
checksum = nosignex(fontfp,(unsigned char)4);
if ((fontptr->c != 0L) && (checksum != 0L) && (fontptr->c != checksum))
{
(void)sprintf(message,
"readpxl(): font [%s] has checksum = 10#%010lu [16#%08lx] [8#%011lo] \
different from DVI checksum = 10#%010lu [16#%08lx] [8#%011lo]. \
TeX preloaded .fmt file is probably out-of-date with respect to new fonts.",
fontptr->name, fontptr->c, fontptr->c, fontptr->c,
checksum, checksum, checksum);
(void)warning(message);
}
fontptr->magnification = nosignex(fontfp,(unsigned char)4);
fontptr->designsize = nosignex(fontfp,(unsigned char)4);
if (fseek(fontfp, (long)(nosignex(fontfp,(unsigned char)4) << 2), 0))
{
(void)warning(
"readpxl(): fseek() did not find PXL font file character directory");
return(EOF);
}
for (the_char = FIRSTPXLCHAR; the_char <= LASTPXLCHAR; the_char++)
{
tcharptr = &(fontptr->ch[the_char]);
tcharptr->wp = (int)nosignex(fontfp,(unsigned char)2);
tcharptr->hp = (int)nosignex(fontfp,(unsigned char)2);
tcharptr->xoffp = (int)signex(fontfp,(unsigned char)2);
tcharptr->yoffp = (int)signex(fontfp,(unsigned char)2);
/* convert (32-bit) word pointer to byte pointer */
tcharptr->fontrp = (long)(nosignex(fontfp,(unsigned char)4) << 2);
tcharptr->tfmw = (unsigned long int)(((double)nosignex(fontfp,(unsigned char)4) *
(double)fontptr->s) / (double)(1L<<20));
tcharptr->pxlw = (unsigned int)PIXROUND((long int)(tcharptr->tfmw), conv);
tcharptr->refcount = 0; /* character unused */
tcharptr->rasters = (unsigned long int*)NULL; /* no raster description */
}
return(0);
}
void reldfont(tfontptr) /* load (or reload) font parameters */
struct font_entry *tfontptr;
{
register unsigned int the_char; /* loop index */
int err_code;
register struct char_entry *tcharptr;/* temporary char_entry pointer */
tfontptr->font_mag = (unsigned long int)((actfact(
MAGSIZE((double)tfontptr->s/(double)tfontptr->d)) *
((double)runmag/(double)STDMAG) *
actfact(mag) *
(double)RESOLUTION * 5.0) + 0.5);
tfontptr->designsize = (unsigned long int)0L;
tfontptr->hppp = (unsigned long int)0L;
tfontptr->vppp = (unsigned long int)0L;
tfontptr->min_m = (long int)0L;
tfontptr->max_m = (long int)0L;
tfontptr->min_n = (long int)0L;
tfontptr->max_n = (long int)0L;
for (the_char = FIRSTPXLCHAR; the_char <= LASTPXLCHAR; the_char++)
{
tcharptr = &(tfontptr->ch[the_char]);
tcharptr->dx = (long int)0L;
tcharptr->dy = (long int)0L;
tcharptr->hp = (int)0;
tcharptr->fontrp = -1L;
tcharptr->pxlw = (unsigned int)0;
tcharptr->rasters = (unsigned long int*)NULL;
tcharptr->refcount = 0;
tcharptr->tfmw = 0L;
tcharptr->wp = (int)0;
tcharptr->xoffp = (int)0;
tcharptr->yoffp = (int)0;
}
if (tfontptr != pfontptr)
(void)openfont(tfontptr->n);
if (fontfp == (FILE *)NULL) /* have empty font with zero metrics */
return;
for (;;) /* fake one-trip loop */
{ /* test for font types PK, GF, and PXL in order of preference */
(void)rewind(fontfp); /* position to beginning-of-file */
if ( ((unsigned char)nosignex(fontfp,(unsigned char)1) == (unsigned char)PKPRE) &&
((unsigned char)nosignex(fontfp,(unsigned char)1) == (unsigned char)PKID) )
{
tfontptr->font_type = (unsigned char)FT_PK;
tfontptr->charxx = (void(*)())charpk;
err_code = readpk();
break;
}
(void)rewind(fontfp); /* position to beginning-of-file */
if ( ((unsigned char)nosignex(fontfp,(unsigned char)1) == (unsigned char)GFPRE) &&
((unsigned char)nosignex(fontfp,(unsigned char)1) == (unsigned char)GFID) )
{
tfontptr->font_type = (unsigned char)FT_GF;
tfontptr->charxx = (void(*)())chargf;
err_code = readgf();
break;
}
(void)rewind(fontfp); /* position to beginning-of-file */
if (nosignex(fontfp,(unsigned char)4) == (unsigned long int)PXLID)
{
tfontptr->font_type = (unsigned char)FT_PXL;
tfontptr->charxx = (void(*)())charpxl;
err_code = readpxl();
break;
}
err_code = (int)EOF;
break;
} /* end one-trip loop */
if (err_code)
{
(void)sprintf(message,
"reldfont(): Font file [%s] is not a valid GF, PK, or PXL file",
tfontptr->name);
(void)fatal(message);
}
}
int rulepxl(number, cnvfac)/* return number of pixels in a rule */
register unsigned long int number;/* in DVI units */
register double cnvfac; /* conversion factor */
{
register int n;
n = (int)(number*cnvfac);
if ((double)n < ((double)(number))*cnvfac)
return((int)(n+1));
else
return((int)n);
}
void setchar(c, update_h)
register unsigned char c;
register int update_h;
{
register struct char_entry *tcharptr; /* temporary char_entry pointer */
if (DBGOPT(DBG_SET_TEXT))
{
(void)fprintf(stderr,"setchar('");
if (isprint(c))
(void)putc(c,stderr);
else
(void)fprintf(stderr,"\\%03o",(int)c);
(void)fprintf(stderr,"'<%d>) (hh,vv) = (%ld,%ld) font name <%s>",
(int)c, (long)hh, (long)vv, fontptr->n);
NEWLINE(stderr);
}
tcharptr = &(fontptr->ch[c]);
if (((hh - tcharptr->xoffp + tcharptr->pxlw) <= XSIZE)
&& (hh >= 0)
&& (vv <= YSIZE)
&& (vv >= 0))
{ /* character fits entirely on page */
moveto( hh, (int)(YSIZE-vv));
dispchar(c);
}
else if (DBGOPT(DBG_OFF_PAGE) && !quiet)
{ /* character is off page -- discard it */
(void)fprintf(stderr,
"setchar(): Char %c [10#%3d 8#%03o 16#%02x] off page.",
isprint(c) ? c : '?',c,c,c);
NEWLINE(stderr);
}
if (update_h)
{
h += (long int)tcharptr->tfmw;
hh += (int)tcharptr->pxlw;
hh = (int)(fixpos(hh-lmargin,h,conv) + lmargin);
}
}
/***********************************************************************
This routine is used to specify the font to be used in printing future
characters.
***********************************************************************/
void setfntnm(k)
register long int k;
{
register struct font_entry *p;
p = hfontptr;
while ((p != (struct font_entry *)NULL) && (p->k != k))
p = p->next;
if (p == (struct font_entry *)NULL)
{
(void)sprintf(message,"setfntnm(): font %ld undefined", k);
(void)fatal(message);
}
else
fontptr = p;
}
/* draw a rule with bottom left corner at (h,v) */
void setrule(height, width, update_h)
register unsigned long int height, width;
register int update_h;
{
if ((height > 0) && (width > 0)) /* non-empty rule */
fillrect(hh, YSIZE-vv,
rulepxl(width,conv),
rulepxl(height, conv * ((double)YDPI/(double)XDPI)));
/* fixed for non 1 aspect */
if (update_h)
{
h += (long int)width;
hh += rulepxl(width, conv);
hh = fixpos(hh-lmargin,h,conv) + lmargin;
}
}
long int signex(fp, n) /* return n byte quantity from file fd */
register FILE *fp; /* file pointer */
register unsigned char n; /* number of bytes */
{
register unsigned char n1; /* number of bytes */
register long int number; /* number being constructed */
number = (long int)getc(fp);/* get first (high-order) byte */
n1 = n--;
while (n--)
{
number <<= 8;
number |= (long int)getc(fp);
}
/* NOTE: This code assumes that the right-shift is an arithmetic, rather
than logical, shift which will propagate the sign bit right. According
to Kernighan and Ritchie, this is compiler dependent! */
number<<=32-8*n1;
number>>=32-8*n1; /* sign extend */
return((long int)number);
}
void skgfspec() /* Skip GF font file specials */
{
unsigned char the_byte;
the_byte = (unsigned char)nosignex(fontfp,(unsigned char)1);
while ((the_byte >= (unsigned char)GFXXX1) && (the_byte != GFPOST))
{
switch(the_byte)
{
case GFXXX1:
(void)fseek(fontfp,(long)nosignex(fontfp,(unsigned char)1),1);
break;
case GFXXX2:
(void)fseek(fontfp,(long)nosignex(fontfp,(unsigned char)2),1);
break;
case GFXXX3:
(void)fseek(fontfp,(long)nosignex(fontfp,(unsigned char)3),1);
break;
case GFXXX4:
(void)fseek(fontfp,(long)nosignex(fontfp,(unsigned char)4),1);
break;
case GFYYY:
(void)nosignex(fontfp,(unsigned char)4);
break;
case GFNOOP:
break;
default:
(void)sprintf(message,"skgfspec(): Bad GF font file [%s]",
fontptr->name);
(void)fatal(message);
}
the_byte = (unsigned char)nosignex(fontfp,(unsigned char)1);
}
(void)ungetc((char)the_byte,fontfp); /* put back lookahead byte */
}
void skipfont( long int k)
{
unsigned char a, l;
char n[MAXSTR];
(void) nosignex(dvifp,(unsigned char)4);
(void) nosignex(dvifp,(unsigned char)4);
(void) nosignex(dvifp,(unsigned char)4);
a = (unsigned char) nosignex(dvifp,(unsigned char)1);
l = (unsigned char) nosignex(dvifp,(unsigned char)1);
getbytes(dvifp, n, (unsigned char)(a+l));
}
void skpkspec() /* Skip PK font file specials */
{
unsigned char the_byte;
the_byte = (unsigned char)nosignex(fontfp,(unsigned char)1);
while ((the_byte >= (unsigned char)PKXXX1) && (the_byte != PKPOST))
{
switch(the_byte)
{
case PKXXX1:
(void)fseek(fontfp,(long)nosignex(fontfp,(unsigned char)1),1);
break;
case PKXXX2:
(void)fseek(fontfp,(long)nosignex(fontfp,(unsigned char)2),1);
break;
case PKXXX3:
(void)fseek(fontfp,(long)nosignex(fontfp,(unsigned char)3),1);
break;
case PKXXX4:
(void)fseek(fontfp,(long)nosignex(fontfp,(unsigned char)4),1);
break;
case PKYYY:
(void)nosignex(fontfp,(unsigned char)4);
break;
case PKNOOP:
break;
default:
(void)sprintf(message,"skpkspec(): Bad PK font file [%s]",
fontptr->name);
(void)fatal(message);
}
the_byte = (unsigned char)nosignex(fontfp,(unsigned char)1);
}
(void)ungetc((char)the_byte,fontfp); /* put back lookahead byte */
}
void special(s) /* process TeX \special{} string in s[] */
register char *s;
{
(void)sprintf(message,
"special(): TeX \\special{%s} not implemented in this driver",s);
(void)warning(message);
}
void outrow(c,yoff) /* copy img_row[] into rasters[] if allocated, else no-op */
unsigned char c; /* current character value */
unsigned int yoff; /* offset from top row (0,1,...,hp-1) */
{
register unsigned int k; /* loop index */
register unsigned long int *p; /* pointer into img_row[] */
register unsigned long int *q; /* pointer into rasters[] */
register struct char_entry *tcharptr; /* temporary char_entry pointer */
unsigned int words_per_row; /* number of raster words to copy */
tcharptr = &(fontptr->ch[c]);
if (tcharptr->rasters != (unsigned long int*)NULL)
{
words_per_row = (unsigned int)(tcharptr->wp + 31) >> 5;
p = tcharptr->rasters + yoff*words_per_row;
q = img_row;
for (k = words_per_row; k; --k) /* copy img_row[] into rasters[] */
*p++ = *q++;
}
}